import os
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
from catcher.backtest import ArbitrageBacktest
from catcher.config import (DATA_PATH, FUTURES_CONFIG, FONT_PATH)
from catcher.warnings_config import configure_warnings
from catcher.pdFile import file_exists, file_to_pd
import traceback

def run_single_backtest(pair_info, initial_capital=1000000):
    """运行单个品种对的回测"""
    # 获取最新的价差数据
    date_string = datetime.now().strftime("%Y-%m-%d")
    
    if file_exists(pair_info['name'], date_string):
        price_data = file_to_pd(pair_info['name'], date_string)
    else:
        print(f"找不到 {pair_info['name']} 的历史数据")
        return None
    
    # 创建保存路径
    save_path = os.path.join(DATA_PATH, "backtest")
    os.makedirs(save_path, exist_ok=True)
    
    # 创建品种专属文件夹
    pair_path = os.path.join(save_path, pair_info['name'])
    os.makedirs(pair_path, exist_ok=True)
    
    # 为每个品种创建新的回测实例
    backtest_system = ArbitrageBacktest(initial_capital=initial_capital)
    
    # 运行回测
    results = backtest_system.run_backtest(price_data, pair_info['name'])
    
    if results is not None:
        # 绘制回测结果图表并保存
        fig = backtest_system.plot_results(results)
        if fig is not None:
            fig.savefig(os.path.join(pair_path, 'backtest_chart.png'))
            plt.close(fig)
        
        # 保存交易记录
        if len(results['交易记录']) > 0:
            trade_records = pd.DataFrame(results['交易记录'])
            trade_records.to_excel(os.path.join(pair_path, 'trade_records.xlsx'), index=False)
    
    # 打印回测结果
    print(f"\n{pair_info['name']} 回测结果:")
    print(f"初始资金: {backtest_system.initial_capital:,.2f}")
    final_equity = results['权益曲线']['equity'].iloc[-1]
    print(f"最终资金: {final_equity:,.2f}")
    print(f"总收益率: {((final_equity - backtest_system.initial_capital) / backtest_system.initial_capital * 100):.2f}%")
    print(f"总交易次数: {results['总交易次数']}")
    print(f"盈利交易次数: {results['盈利次数']}")
    print(f"胜率: {results['胜率']:.2%}")
    print(f"总盈亏: {results['总盈亏']:,.2f}")
    print(f"最大回撤: {results['最大回撤']:,.2f}")
    print(f"夏普比率: {results['夏普比率']:.2f}")
    print("-" * 50)
    
    return results

def save_backtest_report(all_results, save_path):
    """保存回测报告"""
    # 创建总报告
    report = "期货套利策略回测报告\n"
    report += f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
    report += "=" * 50 + "\n\n"
    
    # 汇总所有品种的结果
    summary_data = []
    
    for result in all_results:
        if result is not None:
            # 为每个品种创建单独的文件夹
            pair_path = os.path.join(save_path, result['品种名称'])
            os.makedirs(pair_path, exist_ok=True)
            
            # 保存详细交易记录
            trades_df = result['交易记录']
            trades_df.to_excel(
                os.path.join(pair_path, 'trades_detail.xlsx'),
                index=False
            )
            
            # 保存权益曲线数据
            equity_df = result['权益曲线']
            equity_df.to_csv(
                os.path.join(pair_path, 'equity_curve.csv'),
                index=True
            )
            
            # 生成品种详细报告
            pair_report = f"{result['品种名称']} 回测报告\n"
            pair_report += f"总交易次数: {result['总交易次数']}\n"
            pair_report += f"盈利交易数: {result['盈利次数']}\n"
            pair_report += f"胜率: {result['胜率']:.2%}\n"
            pair_report += f"总盈亏: {result['总盈亏']:,.2f}\n"
            pair_report += f"最大回撤: {result['最大回撤']:,.2f}\n"
            pair_report += f"夏普比率: {result['夏普比率']:.2f}\n"
            
            # 保存品种报告
            with open(os.path.join(pair_path, 'report.txt'), 'w', encoding='utf-8') as f:
                f.write(pair_report)
            
            # 添加到汇总数据
            summary_data.append({
                '品种对': result['品种名称'],
                '总交易次数': result['总交易次数'],
                '盈利交易数': result['盈利次数'],
                '胜率': f"{result['胜率']:.2%}",
                '总盈亏': f"{result['总盈亏']:,.2f}",
                '最大回撤': f"{result['最大回撤']:,.2f}",
                '夏普比率': f"{result['夏普比率']:.2f}"
            })
    
    # 创建汇总表格
    df_summary = pd.DataFrame(summary_data)
    
    # 保存总报告
    report_file = os.path.join(save_path, f"backtest_summary_{datetime.now().strftime('%Y%m%d')}.txt")
    with open(report_file, 'w', encoding='utf-8') as f:
        f.write(report)
        f.write("\n品种汇总统计：\n")
        f.write(df_summary.to_string())
    
    # 保存汇总Excel
    excel_file = os.path.join(save_path, f"backtest_summary_{datetime.now().strftime('%Y%m%d')}.xlsx")
    with pd.ExcelWriter(excel_file) as writer:
        df_summary.to_excel(writer, sheet_name='汇总', index=False)

def check_data_availability():
    """检查数据是否已经获取"""
    date_string = datetime.now().strftime("%Y-%m-%d")
    missing_pairs = []
    
    for name in FUTURES_CONFIG.keys():
        if not file_exists(name, date_string):
            missing_pairs.append(name)
    
    if missing_pairs:
        print("以下期货对缺少历史数据：")
        for pair in missing_pairs:
            print(f"- {pair}")
        print("\n请先运行 fetch_data.py 获取历史数据")
        return False
    return True

def main():
    """主函数"""
    try:
        # 配置警告过滤
        configure_warnings()
        
        # 检查数据可用性
        if not check_data_availability():
            return
        
        # 创建保存路径
        save_path = os.path.join(DATA_PATH, "backtest")
        os.makedirs(save_path, exist_ok=True)
        
        # 设置初始资金
        initial_capital = 1000000
        
        # 使用FUTURES_CONFIG替代TEST_FUTURE_PAIRS
        test_pairs = [
            {
                'name': name,
                'code1': config['code1'],
                'code2': config['code2']
            }
            for name, config in FUTURES_CONFIG.items()
        ]
        
        # 运行所有品种的回测
        all_results = []
        for pair in test_pairs:
            result = run_single_backtest(pair, initial_capital)
            if result is not None:
                all_results.append(result)
        
        # 保存回测报告
        save_backtest_report(all_results, save_path)
        
        print(f"\n回测完成！报告已保存至: {save_path}")
        
    except Exception as e:
        print("\n=== 回测过程出错 ===")
        print(f"错误类型: {type(e).__name__}")
        print(f"错误信息: {str(e)}")
        print("\n完整错误栈:")
        traceback.print_exc()
        raise

if __name__ == "__main__":
    main() 